## package and enviroments:

# library("pacman")
library("dplyr")
library("plyr")
library("ggplot2")
# p_load("stringr")
library("reshape2")
# p_load("PMCMR")
# p_load("ggforce")
library(openxlsx)
library(tidyverse)
# p_load(Loafer)
# get_or_set_dir()

output_path<-"./"

get_demo_codes_for_bar_plots <- function(obj = obj){
  codes <- "
obj <- get_pic_with_labels(input_df = iris[,1:4,drop = F],
                           # input_df$Sepal.Length <- rnorm(nrow(input_df)),
                           group_info_df = iris[,5,drop = F],
                           group_index = 1,
                           group_levels_in_order_C = group_info_df[,1] %>% unique(),
                           test_pattern  = 'para' ,
                           # test_pattern  = 'wise' ,
                           # test_pattern  = 'non-para' %>% tolower(),
                           p_for_label = 'p_all',
                           unify_step_as_constant = T, ### Very important when drawing different variables in same row(with fixed y value.)
                           step = 0.15, # Modify the vertical distances between significant label codes.
                           draw_pics = F,
                           position_by = 'max meanse')


variables_c <- obj@pic_long_df$variable %>% unique
page_num <- variables_c %>% length
segment_size <- .7 ## The size of the segement
# each_page <- 1
obj@pic_long_df
# for(each_page in 1:page_num){

# each_meta <- variables_c[each_page]
obj@pic_long_df %>% head
pic <- ggplot(obj@pic_long_df) +
    ## error bar by mean ± se
    geom_errorbar( aes(x= group, ymin=mean-se, ymax=mean+se),
                   width=0.4, colour='black', alpha=0.9, size=1.3) +
    geom_bar(aes(x = group, y = mean, group = group, fill = group), data = obj@pic_long_df ,
             # size  = .8,
             position = position_dodge(),
             stat='identity'
             # outlier.colour = 'white',
             # width = 2,

    )+
    theme_bw()+
    facet_wrap(facets = vars(variable), nrow = 1, scales = 'fixed')+
    theme(
        text = element_text(size = 18, color = 'black'),
        axis.text.y = element_text( size = 12, face = 'bold', color = 'black'),
        axis.text.x = element_text( size = 12, face = 'bold', color = 'black'),
        strip.text.x = element_text(size = 16, color = 'black'),
        panel.grid = element_blank()
    )
pic
pic <- pic +
    geom_segment(data = obj@label_position_df,
                 aes(x = start_num, xend = start_num + 0.25 * (end_num - start_num),
                     y = label.y, yend = label.y), lineend = 'butt', size = segment_size)+
    geom_segment(data = obj@label_position_df,
                 aes(x = end_num, xend = start_num + 0.75 * (end_num - start_num),
                     y = label.y, yend = label.y),
                 lineend = 'butt', size = segment_size)+
    geom_text(data = obj@label_position_df,
              aes(x = 0.5*(start_num + end_num), y = label.y*1.007, label = label)
              ,color = 'black', size = 8) +
    geom_segment(data = obj@label_position_df, aes(x = start_num, xend = start_num, y = label.y, yend = label.y * .99), lineend = 'round', size = segment_size)+
    geom_segment(data = obj@label_position_df, aes(x = end_num, xend = end_num, y = label.y, yend = label.y * .99), lineend = 'round', size = segment_size)+
    geom_segment(data = obj@label_position_df, aes(x = start_num, xend = end_num, y = label.y, yend = label.y),
                 size = segment_size) +
    xlab('Group')+
    ylab('Concentration (μmol/L)')+
    scale_y_continuous(expand = expansion(c(0.05,0.05)))
pic

plot_name <- sprintf('plot with sig labels.pdf')

ggsave(plot_name, plot = pic, width = 5, height = 4,
       limitsize = F, family = 'serif')




df <- data.frame(x = rep(c(2.9, 3.1, 4.5), c(5, 10, 4)))
ggplot(df, aes(x)) + geom_bar()
"
  obj@demo_code_for_barplot <- codes
  return(obj)
}

draw_plot_with_labels <- function(obj,  draw_pics = draw_pics){

  if(draw_pics == T){
    'obj represent the result of the function'
    variables_c <- obj@pic_long_df$variable %>% unique
    page_num <- variables_c %>% length
    segment_size <- .7 ## The size of the segement
    # each_page <- 1
    obj@pic_long_df
    for(each_page in 1:page_num){

      each_meta <- variables_c[each_page]
      # each_meta

      # pic_df_new$variable <- pic_df_new$variable %>% sub("\\.", " ", .)
      # pic_df_new <- pic_df[pic_df$variable %in% variable,]
      pic <- ggplot(obj@pic_long_df) +
        # geom_errorbar(aes(x = group,  ymax = mean + se, ymin = mean - se, ## 将最小值藏起来。
        #                   color = group, group = group),
        #               width = 0.45, size = 0.6, color = "black")+
        ## the key to do this is move aes attr into the following geom_XXXX line. Insdead of the first line.
        # geom_bar(stat  = "identity", aes(x = group, y = mean(value), fill = group, group = group))+
        # geom_bar(aes(x = group, y = mean, fill = group, group = group),
        #          stat = "identity", position = "identity")+
        # geom_bar(aes(x = group, y = mean/count, fill = group, group = group), stat = "identity", position = "fill")+
        geom_boxplot(aes(x = group, y = value), data = obj@pic_long_df, outlier.colour = "white",
                     # width = 2,
                     size  = .8)+
        theme_bw()+
        # geom_bar(aes(x = group, y = mean, fill = group, group = group),
        #          stat = "identity", position = "identity")+
        geom_point(aes(x = group, y = value), shape = 21, color = "black", fill = "red",
                   position = position_jitter(width = .15, height = 0), size = 1.3, alpha = .8)+
        # facet_wrap(facets = vars(variable), ncol = 3, scales = "free")+
        facet_wrap_paginate(facets = vars(variable), scales="free", ncol = 1, nrow = 1, page = each_page)+
        # scale_fill_manual(values = color_vector_c)+
        theme(
          text = element_text(size = 18, color = "black"),
          # legend.title = element_text(size = 22, color = "black"),
          # legend.text = element_text(size = 18, color = "black"),
          axis.text.y = element_text( size = 12, face = "bold", color = "black"),
          axis.text.x = element_text( size = 12, face = "bold", color = "black"),
          strip.text.x = element_text(size = 16, color = "black"),
          # axis.text.x = element_blank(),
          ### 加横坐标，去除网格线。
          panel.grid = element_blank()
        )

      pic <- pic +
        geom_segment(data = obj@label_position_df,
                     aes(x = start_num, xend = start_num + 0.25 * (end_num - start_num),
                         y = label.y, yend = label.y), lineend = "butt", size = segment_size)+
        geom_segment(data = obj@label_position_df,
                     aes(x = end_num, xend = start_num + 0.75 * (end_num - start_num),
                         y = label.y, yend = label.y),
                     lineend = "butt", size = segment_size)+
        # geom_shadowtext(data = final_label_df,
        #                 aes(x = 0.5*(start_num + end_num),
        #                     y = label.y, label = label),
        #                 size = 5.5, bg.colour='firebrick') +
        geom_text(data = obj@label_position_df,
                  aes(x = 0.5*(start_num + end_num), y = label.y*1.007, label = label)
          ,color = "black", size = 8) +
        geom_segment(data = obj@label_position_df, aes(x = start_num, xend = start_num, y = label.y, yend = label.y * .99), lineend = "round", size = segment_size)+
        geom_segment(data = obj@label_position_df, aes(x = end_num, xend = end_num, y = label.y, yend = label.y * .99), lineend = "round", size = segment_size)+
        # geom_segment(data = final_label_df, aes(x = end_num, xend = end_num, y = label.y, yend = label.y * .99), lineend = "round", size = segment_size) +
        geom_segment(data = obj@label_position_df, aes(x = start_num, xend = end_num, y = label.y, yend = label.y),
                     size = segment_size) +
        xlab("Group")+
        ylab("Concentration (μmol/L)")+
        scale_y_continuous(expand = expansion(c(0.05,0.05)))
      ### geom_text can be reguarded as num value when the x shows factor variable.

      plot_name <- sprintf("%splot with sig labels #%s.pdf", output_path, each_meta)

      ggsave(plot_name, plot = pic, width = 5, height = 4,
             limitsize = F, family = "serif")

    }
  }


  demo_code <- "'obj represent the result of the function'
    variables_c <- obj@pic_long_df$variable %>% unique
    page_num <- variables_c %>% length
    segment_size <- .7 ## The size of the segement
    # each_page <- 1
    obj@pic_long_df
    for(each_page in 1:page_num){

        each_meta <- variables_c[each_page]

        pic <- ggplot(obj@pic_long_df) +
            # geom_errorbar(aes(x = group,  ymax = mean + se, ymin = mean - se, ## 将最小值藏起来。
            #                   color = group, group = group),
            #               width = 0.45, size = 0.6, color = 'black')+
            ## the key to do this is move aes attr into the following geom_XXXX line. Insdead of the first line.
            # geom_bar(stat  = 'identity', aes(x = group, y = mean(value), fill = group, group = group))+
            # geom_bar(aes(x = group, y = mean, fill = group, group = group),
            #          stat = 'identity', position = 'identity')+
            # geom_bar(aes(x = group, y = mean/count, fill = group, group = group), stat = 'identity', position = 'fill')+
            geom_boxplot(aes(x = group, y = value), data = obj@pic_long_df, outlier.colour = 'white',
                         # width = 2,
                         size  = .8)+
            theme_bw()+
            # geom_bar(aes(x = group, y = mean, fill = group, group = group),
            #          stat = 'identity', position = 'identity')+
            geom_point(aes(x = group, y = value), shape = 21, color = 'black', fill = 'red',
                       position = position_jitter(width = .15, height = 0), size = 1.3, alpha = .8)+
            # facet_wrap(facets = vars(variable), ncol = 3, scales = 'free')+
            facet_wrap_paginate(facets = vars(variable), scales='free', ncol = 1, nrow = 1, page = each_page)+
            # scale_fill_manual(values = color_vector_c)+
            theme(
                text = element_text(size = 18, color = 'black'),
                # legend.title = element_text(size = 22, color = 'black'),
                # legend.text = element_text(size = 18, color = 'black'),
                axis.text.y = element_text( size = 12, face = 'bold', color = 'black'),
                axis.text.x = element_text( size = 12, face = 'bold', color = 'black'),
                strip.text.x = element_text(size = 16, color = 'black'),
                # axis.text.x = element_blank(),
                ### 加横坐标，去除网格线。
                panel.grid = element_blank()
            )

        pic <- pic +
            geom_segment(data = obj@label_position_df,
                         aes(x = start_num, xend = start_num + 0.25 * (end_num - start_num),
                             y = label.y, yend = label.y), lineend = 'butt', size = segment_size)+
            geom_segment(data = obj@label_position_df,
                         aes(x = end_num, xend = start_num + 0.75 * (end_num - start_num),
                             y = label.y, yend = label.y),
                         lineend = 'butt', size = segment_size)+
            # geom_shadowtext(data = final_label_df,
            #                 aes(x = 0.5*(start_num + end_num),
            #                     y = label.y, label = label),
            #                 size = 5.5, bg.colour='firebrick') +
            geom_text(data = obj@label_position_df,
                      aes(x = 0.5*(start_num + end_num), y = label.y*1.007, label = label)
                      ,color = 'black', size = 8) +
            geom_segment(data = obj@label_position_df, aes(x = start_num, xend = start_num, y = label.y, yend = label.y * .99), lineend = 'round', size = segment_size)+
            geom_segment(data = obj@label_position_df, aes(x = end_num, xend = end_num, y = label.y, yend = label.y * .99), lineend = 'round', size = segment_size)+
            # geom_segment(data = final_label_df, aes(x = end_num, xend = end_num, y = label.y, yend = label.y * .99), lineend = 'round', size = segment_size) +
            geom_segment(data = obj@label_position_df, aes(x = start_num, xend = end_num, y = label.y, yend = label.y),
                         size = segment_size) +
            xlab('Group')+
            ylab('Concentration (μmol/L)')+
            scale_y_continuous(expand = expansion(c(0.05,0.05)))
        ### geom_text can be reguarded as num value when the x shows factor variable.

        plot_name <- sprintf('%splot with sig labels #%s.pdf', output_path, each_meta)

        ggsave(plot_name, plot = pic, width = 5, height = 4,
               limitsize = F, family = 'serif')

    }"

  obj@demo_code <- demo_code

  return(obj)
}

return_label.y <- function(max_in_range = each_df$max_value[needs_position],
                           ylim_max, ## max in the data
                           step_height,
                           fixed_step = F,
                           obj,
                           first_stepdown_adjust = 0.7){


  "# max_in_range = each_df$max_value[needs_position]"

  if(obj@unify_step_as_constant == T &
    obj@get_step_by_max_instead_of_range == T){
    step_height <- obj@max_value_overall * obj@step
  }else if(obj@unify_step_as_constant == T){
    step_height <- obj@unify_step_by_max_range * obj@step
  }else if(obj@get_step_by_max_instead_of_range == T){
    step_height <- max(ylim_max) * obj@step
  }


  first_step_height <- (1 - first_stepdown_adjust) *  step_height ## First label distance from data max.
  label.y <- NULL
  label.y[1] <- max_in_range[1] + first_step_height
  len <- max_in_range %>% length
  if(len > 1){
    for(k in 2:len){
      y1 <- label.y[k-1] + step_height
      y2 <- max_in_range[k] + first_step_height
      label.y[k] <- max(y1, y2)
    }
  }
  return(label.y)
}

get_position_by_max_single_value <- function(obj){

  final_df <- obj@label_position_df


  final_df <- order(final_df$variable, final_df$label != "   ",
                    final_df$ylim_max, final_df$range,final_df$start_num) %>% final_df[.,]

  # each_df <- final_df[1:4,]
  final_df <- final_df %>% ddply(., "variable", function(each_df){
    sig_counts <- (each_df$label != "   ") %>% sum()


    if(sig_counts >0){ ## if has some sig pairs. then calculate the position.

      ## start calculate the position since the nrow - sig_counts + 1
      needs_position <- (nrow(each_df) - sig_counts + 1):nrow(each_df)
      ## with consideration of the max_value.
      # each_df$label.y[needs_position] <-  each_df$ylim_range[1] * obj@step * seq_along(needs_position) + each_df$ylim_max[needs_position]

      if(length(needs_position)>=1){
        # each_df$label.y[needs_position] <- recheck_label_position(raw_position = each_df$label.y[needs_position], ## original position
        #                                                           max_in_range = each_df$ylim_max[needs_position], ## base supposed to add height on and put label on it.
        #                                                           step_height = each_df$ylim_range[1] * obj@step) ## each_step.
        ### set a function to du this things.
        each_df$label.y[needs_position] <- return_label.y(max_in_range = each_df$ylim_max[needs_position],
                                                          step_height = each_df$ylim_range[1] * obj@step,
                                                          obj = obj,
                                                          ylim_max = each_df$ylim_max,
                                                          first_stepdown_adjust = 0.7)

      }


      # each_df$label.y_for_total <- each_df$label.y %>% max(., na.rm = T) ### useful for total p mapping.
    }
    each_df$each_step_height <- each_df$ylim_range[1] * obj@step
    return(each_df)
  })

  obj@label_position_df <- final_df
  return(obj)
}

subset_group_pairs <- function(obj, group_pairs_to_show){
  ori_df <- obj@label_position_df
  for(i in 1:length(group_pairs_to_show)){
    if(i == 1){final <- rep(F, nrow(ori_df))}
    qualified_c <- (ori_df$pair1 == group_pairs_to_show[[i]][1] & ori_df$pair2 == group_pairs_to_show[[i]][2])|(ori_df$pair1 == group_pairs_to_show[[i]][2] & ori_df$pair2 == group_pairs_to_show[[i]][1])
    final <- final|qualified_c
  }
  ori_df <- ori_df[final,]
  obj@label_position_df <- ori_df
  return(obj)
}

get_label_position_df <- function(obj){
  df_with_labels <- obj@result_df
  summary_of_df <- obj@pic_long_df
  level_to_num_C <-  seq_along(obj@group_levels_in_order_C)
  names(level_to_num_C) <- obj@group_levels_in_order_C

  for(i in 1:nrow(df_with_labels)){
    if(i == 1){final_df <- data.frame(stringsAsFactors = F, check.names = F)}
    df <- df_with_labels[i,]
    df <- df %>% mutate(.,
                        start_num = min(df$pair1 %>% level_to_num_C[.], df$pair2 %>% level_to_num_C[.]),
                        end_num = max(df$pair1 %>% level_to_num_C[.], df$pair2 %>% level_to_num_C[.]),
                        range = end_num - start_num)
    # df

    ## qualified_rows selected the group involved in the range of the group. either they are start，ending or the middle part.
    qualified_rows <- summary_of_df$variable == df$variable & summary_of_df$group_num >= df$start_num & summary_of_df$group_num <= df$end_num
    max_value <- summary_of_df$max[qualified_rows] %>% unlist %>% max
    min_value <- summary_of_df$max[qualified_rows] %>% unlist %>% min
    df$max_value <- max_value
    df$min_value <- min_value
    df
    df$maxmeanse <- (summary_of_df$mean[qualified_rows] + summary_of_df$se[qualified_rows]) %>% unlist %>% max
    mean <- summary_of_df$mean[qualified_rows] %>% unlist %>% max
    # sd  _max <- summary_of_df$sd[qualified_rows] %>% unlist %>% min
    final_df <- rbind(final_df, df)
    final_df
  }



  ## Get the max and min of the variable through all the groups.
  final_df <- final_df %>% ddply(., "variable", function(each_df){
    each_df$ylim_max <- each_df$max_value %>% max()
    each_df$ylim_min <- each_df$min_value %>% min()
    each_df$ylim_range <- each_df$ylim_max - each_df$ylim_min
    # each_df$maxmeanse
    return(each_df)
  })
  obj@unify_step_by_max_range <- final_df$ylim_range %>% max
  obj@max_value_overall <- final_df$ylim_max %>% max


  obj@label_position_df <- final_df
  return(obj)
}

neat_round <- function(num,digits=3){  " version 5.0 "
  options(scipen = 200)## 要加一个科学计数法位数拓展
  num <- round(num,digits = digits)
  zheng_shu_bu_fen  <- trunc(num)
  zheng_shu_char <- sub("([-+]?[0-9]+)\\.[0-9]*",
                        "\\1",num)###利用正则表达式提取整数部分，防止0开头的负小数时，符号被忽略
  #核心工作流程： 先取绝对值再加1,（确保不是0打头），乘以10的有效位数次方——最后需要的全部都跑到了小数点左边（可以被截取）
  # #然后刨除前面整数部分，取后面的小数部分进行衔接。
  new_xiao_shu <-  abs(num-zheng_shu_bu_fen)  ### 用原数值减整数部分直接得到小数部分,取绝对值,保障是正数. 且首位是0
  new_xiao_shu <- new_xiao_shu+0.1^(digits+1) ### 保留 n位 小数, 就加一个小数点后 n个0,1个1的数,使前面的零强制显示
  xiao_shu_bu_fen <- substr(new_xiao_shu,3,2+digits)
  final <- paste(zheng_shu_char,".",xiao_shu_bu_fen,sep = "")
  return(final)
}

p_to_label <- function (input, digits = 4, breaks = c(-0.00000000001, 0.001,
                                                              0.01, 0.05, 1.0001), labels = c("***", "* *",
                                                                                              " * ", "   "), trans_to_character = T, drop_p = T,
                                include_right_bound = F)
{
  cat(" <0.001, <0.01, <0.05 and <= 1 were used to cut the raw p values in default ")
  label_vector <- cut(input, breaks, labels, right = include_right_bound)
  neat_number <- neat_round(input, digits = digits)
  if (trans_to_character == T) {
    neat_number[input < 0.0001] <- "<0.0001"
  }
  if (drop_p == T) {
    output <- label_vector
  }
  else {
    output <- paste(neat_number, label_vector)
  }
  return(output)
}


nth_col_as_rowname <- function (df, nth = 1, drop_before_nth = T)
{
  rownames(df) <- df[, nth]
  if (drop_before_nth == T) {
    df <- df[, -c(1:nth), drop = F]
  }
  return(df)
}

add_labels_into_result_df <- function(obj = obj){
  df_with_labels <- obj@result_df
  df_with_labels$p_for_label <- df_with_labels[,obj@p_for_label]
  df_with_labels$label <- df_with_labels$p_for_label %>% as.numeric %>%
    p_to_label(breaks = c(-1,0.001,0.01,0.05,1.1), labels =c("***","* *"," * ","   "))
  obj@result_df <- df_with_labels
  return(obj)
}

get_long_df <- function(obj = obj){
  wide_df <- data.frame(Sample_ID = rownames(obj@input_df), obj@df_for_test,
                        check.names = F, stringsAsFactors = F)
  long_df <- wide_df %>% melt(data = ., id.vars = c("Sample_ID","group"),
                              variavle.name = "variable", value.name = "value")


  level_to_num_C <-  seq_along(obj@group_levels_in_order_C)
  names(level_to_num_C) <- obj@group_levels_in_order_C

  long_df <- long_df %>% ddply(., c("variable", "group"),function(each_df){


    each_df$group_num <-  each_df$group[1] %>% level_to_num_C[.]
    each_df$mean <- each_df$value %>% mean(., na.rm = T)
    each_df$median   <- each_df$value %>% median(., na.rm = T)
    each_df$sd   <- each_df$value %>% sd(., na.rm = T)
    # each_df$sem <- each_df$sd/(nrow(each_df)**.5)
    each_df$se <- each_df$sd/sqrt(nrow(each_df)) ## Standard Error
    each_df$CI <- qt((1-0.05)/2 + .5, nrow(each_df) - 1) * each_df$se ##  Confidence Interval for alpha = 0.05.

    each_df$max <- each_df$value %>% max(., na.rm = T)
    each_df$min <- each_df$value %>% min(., na.rm = T)
    each_df$mean <-  each_df$value %>% mean(., na.rm = T)
    each_df$sd <-  each_df$value %>% sd(., na.rm = T)
    each_df$median <-  each_df$value %>% median(., na.rm = T)
    each_df$IQR_Q1 <- each_df$value %>% quantile(., 0.25,na.rm = T)
    each_df$IQR_Q3 <- each_df$value %>% quantile(., 0.75,na.rm = T)

    # each_df$count <- nrow(each_df)
    # each_df$max <- max(each_df$value, na.rm = T)
    # each_df$min <- min(each_df$value, na.rm = T)
    # each_df$range <-
    # each_df$IQR   <- each_df$value %>% median(., na.rm = T)
    return(each_df)
  }) # %>% head

  ### 适配了多组时自动拆分生成 pair1 和 pair 2 变量。
  if("pairwise_group" %in% colnames(obj@result_df) ){
    obj@result_df$pair1 <-  obj@result_df$pairwise_group %>% sub("(.*)-(.*)", "\\1",.)
    obj@result_df$pair2 <-  obj@result_df$pairwise_group %>% sub("(.*)-(.*)", "\\2",.)
  }
  ### 需要自动适配 两组比较的情况：

  if(length(obj@group_levels_in_order_C) == 2){
    obj@result_df$pair1 <- obj@group_levels_in_order_C[1]
    obj@result_df$pair2 <- obj@group_levels_in_order_C[2]
  }

  obj@pic_long_df <- long_df
  return(obj)
}

para_compare <- function(temp_df = temp_df){
  # input item:
  ## temp_df: a dataframe.
  ## first col was group and named as "group"
  ## second col was variable value and named as "Value"
  temp_df$group <- temp_df$group %>% factor()
  fit <- aov(value ~ group, data = temp_df)
  p_all <-  summary(fit)[[1]][["Pr(>F)"]][[1]] ##  get p value
  if(is.na(p_all)){p_all <- 1}
  ## different reaction depended on the numbers of the groups selected.
  if(temp_df$group %>% unique() %>% length() == 2){
    # temp_df$group
    final_df <-  data.frame(IS_Para = "Para", p_all, stringsAsFactors = F, check.names = F)
  }else{
    Tukeyresult <-  TukeyHSD(fit, "group")
    # Tukeyresult
    Tukeyresult_df <- Tukeyresult$group %>% data.frame(.,stringsAsFactors = F)
    pairwise_group <- rownames(Tukeyresult_df)
    Tukeyresult_df$p.adj[is.na(Tukeyresult_df$p.adj)] <- 1
    pairwise_p.adj     <-  Tukeyresult_df$p.adj

    # Tukeyresult
    p_raw <- pairwise.t.test(x = temp_df$value, g = temp_df$group,
                             paired = F, p.adjus.method = "none")
    p_raw.df <- p_raw$p.value %>% melt
    p_raw.df$value[is.na(p_raw.df$value)] <- 1
    match_num <- match(rownames(Tukeyresult_df), paste(p_raw.df[,1], p_raw.df[,2], sep = "-"))
    p_raw.df <- match_num %>% p_raw.df[.,]
    pairwise_p.raw <- p_raw.df$value

    # class(Tukeyresult_df)
    final_df <-  data.frame(
      # Treat,## compare method deprecated。
      IS_Para = "Para",
      # variable_name,##  variable name, deprecated
      # statistics_all,
      p_all, # p between any two groups
      pairwise_group,
      pairwise_p.raw,
      pairwise_p.adj # Tukey p adj
      ,stringsAsFactors = F)
  }

  final_df$p_all[is.na(final_df$p_all)] <- 1
  final_df %>% return()
}

single_col_test <- function(obj = obj, temp_df = temp_df, var_name = var_name){
  obj@test_pattern
  if(obj@test_pattern == "wise"){
    ## if wise pattern was choosen. then the wether para test was carried out.
    IS_para <- wether_para(temp_df = temp_df)
  } else {IS_para = obj@test_pattern}
  if(IS_para == "para") {
    result_df <- para_compare(temp_df = temp_df)
  }else{
    result_df <- non_para_compare(temp_df = temp_df)
  }
  result_df <- data.frame(Variable = var_name, result_df)
  result_df %>% return
}

compare_by_col <- function(obj = obj){
  # obj$data_cleaned
  for(i in 2:ncol(obj@df_for_test)){
    # if(i == 2){pulled_result_df <- data.frame(check.names = F, stringsAsFactors = F)}
    if(i == 2){pulled_result_df <- NULL}
    temp_df <- obj@df_for_test[,c(1,i)]
    var_name <- colnames(obj@df_for_test)[i]
    colnames(temp_df) <- c("group","value")
    test_result_df <- single_col_test(obj = obj,
                                      temp_df = temp_df,
                                      var_name = var_name) ## test by every single col.
    pulled_result_df <- rbind(pulled_result_df, test_result_df)
  }
  colnames(pulled_result_df)[1] <- "variable"
  obj@result_df <- pulled_result_df
  return(obj)
}

get_pic_with_labels <- function(input_df = iris[,1:4],
                                # input_df$Sepal.Length <- rnorm(nrow(input_df)),
                                group_info_df = iris[,5,drop = F],
                                group_index = 1,
                                group_levels_in_order_C = group_info_df[,1] %>% unique(),
                                test_pattern  = "para" ,
                                # test_pattern  = "wise" ,
                                # test_pattern  = "non-para" %>% tolower(),
                                p_for_label = "p_all",
                                step = 0.05,
                                group_pairs_to_show = NULL,
                                unify_step_as_constant = F,
                                get_step_by_max_instead_of_range = T,
                                draw_pics = F,
                                position_by = "max single value"){
{ # initialize the object for analysis.
  setClass("obj_for_analysis",
           slots = list(input_df = "data.frame", ## input raw data.
                        group_info_df = "data.frame", ## input group information.
                        df_for_test = "data.frame", ## data to be used for compare.
                        ## group order to be shown in pic.
                        group_levels_in_order_C ="vector",
                        step = "numeric",

                        p_for_label = "character",  ## generate label based on chosen p
                        test_pattern = "character",
                        demo_code = "character",
                        demo_code_for_barplot = "character",
                        ## output results:
                        result_df = "data.frame", ## Compare results, P and label. Data results
                        ## data.frame for plot:
                        unify_step_as_constant = "vector",
                        get_step_by_max_instead_of_range = "vector",
                        unify_step_by_max_range = "numeric",
                        max_value_overall = "numeric",

                        pic_long_df = "data.frame", ## df for points in pic.
                        label_position_df = "data.frame" ## df for labels and position in pic.
           ))


  group_info_df <- group_info_df[,group_index] %in% group_levels_in_order_C %>% group_info_df[.,,drop = F]
  input_df  <- rownames(group_info_df) %>% input_df[.,,drop = F] ## reorder the input_df.
  colnames(group_info_df)[group_index] <- "group"
  df_for_test <- data.frame(group = group_info_df[,group_index], input_df,
                            check.names = F, stringsAsFactors = F)




  obj <- new("obj_for_analysis",
             df_for_test = df_for_test,
             input_df = input_df,
             step = step,
             unify_step_as_constant = unify_step_as_constant,
             get_step_by_max_instead_of_range = get_step_by_max_instead_of_range,
             p_for_label = p_for_label,
             group_levels_in_order_C = group_levels_in_order_C,
             # group_index = group_index,
             test_pattern = test_pattern %>% tolower(),
             group_info_df = group_info_df )
  ## get the data used for the later test.
}

  obj <- compare_by_col(obj)

  ## get long_df for pic
  obj <- get_long_df(obj)
  obj <- add_labels_into_result_df(obj)

  obj <- get_label_position_df(obj)
  # obj@label_position_df

  ## keep compares between selected groups and remove others.
  # obj@label_position_df

  if(length(group_pairs_to_show) != 0){
    obj <- subset_group_pairs(obj = obj, group_pairs_to_show = group_pairs_to_show)
  }

  obj@label_position_df
  if(position_by == "max meanse"){
    obj <- get_position_by_max_meanse(obj)
  } else {
    obj <- get_position_by_max_single_value(obj)
  }

  obj@label_position_df <- (obj@label_position_df$label != "   ") %>% obj@label_position_df[.,]
  obj <- draw_plot_with_labels(obj, draw_pics = draw_pics)
  obj <- get_demo_codes_for_bar_plots(obj)
  cat("\n\nTry >>'cat(obj@demo_code)'<< to see the code for boxplot visualization.
           \nTry >>'cat(obj@demo_code_for_barplot)'<< to see the code for barplot\n
        obj means the obj returned by this function.")

  ## order the group variable for plot
  obj@pic_long_df$group <- obj@pic_long_df$group %>%
    factor(., levels = group_levels_in_order_C, ordered = T)


  obj@label_position_df$variable <- obj@label_position_df$variable %>%
    factor(., levels = obj@pic_long_df$variable %>% levels, ordered = T)
  return(obj)
}

# temp <- c(0.01, 0.11, 0.21, 0.31, 0.41, 0.51, 0.61, 0.71, 0.9, 0.91)
# 0.01*
# 
# p.adjust(temp, method = "fdr")

# {
#     input_df = each_df
#     # input_df$Sepal.Length <- rnorm(nrow(input_df)),
#     group_info_df = group_df
#     group_index = group_index_or_name
#     group_levels_in_order_C = group_df[,group_index_or_name] %>% unique()
#     # group_levels_in_order_C = c("WT+BCAAs", "KO+BCAAs"),
#     test_pattern  = 'para' 
#     # test_pattern  = 'wise' ,
#     # test_pattern  = 'non-para' %>% tolower(),
#     # choose one of the p value.
#     p_for_label = "pairwise_p.raw"
#     # p_for_label = "pairwise_p.adj",
#     # p_for_label = "p_all",
#     step = 0.04 # Modify the vertical distances between significant label codes.
#     
#     draw_pics = F
#     unify_step_as_constant = F
#     position_by = 'max meanse'
#     
#     
#     unify_step_as_constant = F
#     get_step_by_max_instead_of_range = T
#     draw_pics = F
#     # p_for_label = "p_all"
#     # group_levels_in_order_C = c("WT+BCAAs", "KO+BCAAs")
#     
# }


## 
# get_or_set_dir()

#' @description 
#' group_df 存放分组信息。行名样本名，第一列分组
#' group_order_c 分组顺序，按照分组的实际顺序展示
#' df 存放原始信息数据，行名样本名，后面是数据
#'   each_note 存放注释，用于改变输出文件的名称
#'   group_pairs_to_show 要展示的分组对子

{
    sheetnum <- 1
    each_note <- "High" ## note
}

{
    sheetnum <- 2
    each_note <- "Low" ## note
}



# p_for_label = "pairwise_p.raw"
p_for_label = "pairwise_p.adj"
each_note <- paste(each_note, p_for_label)

group_index_or_name <- 1
my_color = c()
group_pairs_to_show <- list(c("NCD","NCDG"), c("NCD", "HFD"), c("HFD", "HFDG"), c("HFDG", "HFDGA"))

df0 <- read.xlsx("P233胆汁酸数据处理新0406.xlsx", sheet = sheetnum, startRow = 2)
df0 <- df0 %>%
  column_to_rownames("sample")
df <- df0[,-c(1:2)]
group_df <- df0[, 1, drop = F]

meta_class_df <-  read.xlsx("P233胆汁酸数据处理新0406.xlsx", sheet = 3, startRow = 1)

{## Get colors
    color_df <- read.xlsx("P233胆汁酸数据处理新0406.xlsx", sheet = 4, startRow = 1) %>%
      column_to_rownames("Group")
    print(color_df)
    my_color <- color_df[,2]
    names(my_color) <- rownames(color_df)
}


{
    
    # temp_df <- df 
    # each_df <- temp_df %>% t %>% data.frame(., stringsAsFactors = F, check.names = F)
    each_df <- df
    
    number_in_row <- ncol(each_df)
    
    obj <- get_pic_with_labels(input_df = each_df,
                               # input_df$Sepal.Length <- rnorm(nrow(input_df)),
                               group_info_df = group_df,
                               group_index = group_index_or_name,
                               group_levels_in_order_C = group_df[,group_index_or_name] %>% unique(),
                               # group_levels_in_order_C = c("WT+BCAAs", "KO+BCAAs"),
                               test_pattern  = 'para' ,
                               # test_pattern  = 'wise' ,
                               # test_pattern  = 'non-para' %>% tolower(),
                               # choose one of the p value.
                               p_for_label = p_for_label,
                               # p_for_label = "pairwise_p.adj",
                               group_pairs_to_show = group_pairs_to_show,
                               # p_for_label = "p_all",
                               # step = 0.05, # Modify the vertical distances between significant label codes.
                               step = 0.04, # Modify the vertical distances between significant label codes.
                               draw_pics = F, 
                               get_step_by_max_instead_of_range = T,
                               unify_step_as_constant = T,
                               position_by = "max_single_value")   
    # obj@label_position_df$label.y
    p <- obj@result_df$p_for_label
    # obj@label_position_df$label <- obj@label_position_df$label %>% factor(., levels = c("***", "* *", " * "), labels = c("*\n*\n*\n", "*\n*\n", "*\n"))
    # obj@label_position_df$label <- obj@label_position_df$label %>% factor(., levels = c("***", "* *", " * "), labels = c("+++", " ++", "  +"))
    variables_c <- obj@pic_long_df$variable %>% unique
    
    page_num <- variables_c %>% length
    segment_size <- .7 ## The size of the segement
    
    obj@pic_long_df %>% head
    
    
    variable_factors_c <- (obj@pic_long_df$mean + obj@pic_long_df$se) %>% order(., decreasing = T) %>% obj@pic_long_df[.,"variable"] %>% unique()
    
    obj@pic_long_df$variable <- obj@pic_long_df$variable %>% factor(., levels = variable_factors_c, ordered = T)
    obj@pic_long_df %>% head
    pic <- ggplot(obj@pic_long_df) + 
        ## error bar by mean ± se
        
        geom_errorbar(aes(x= group, ymin=mean-se, ymax=mean+se, colour = group),
                      width=0.5, #colour='black', 
                      alpha=0.9, size=.7) +
        # geom_errorbar(aes(x= group, ymin=mean-se, ymax=mean+se),  
        # color = "yellow", fill = "blue", 
        # width=0.5, colour='black', alpha=0.9, size=1.1) +
        
        geom_bar(aes(x = group, y = mean, group = group, fill = group), data = obj@pic_long_df , 
                 # size  = .8,
                 position = position_dodge(),
                 stat='identity'
                 # outlier.colour = 'white',
                 # width = 2,
        )+
        
        geom_point(aes(x = group, y = value, shape = group), fill = "black",
                   size = 1.2, position = position_jitter(width = 0.1, height = 0))+
        
        xlab(NULL)+
        ylab("nmol/g")+
        scale_y_continuous(expand = expansion(c(0.0,0.05)))+
        theme_bw()+
        scale_shape_manual(values = c(21:22,24:25,23), guide = 'none')+
        scale_fill_manual(values = my_color) + 
        scale_colour_manual(values = my_color, guide = 'none') + 
        theme(
            text = element_text(size = 18, color = 'black'),
            axis.text.y = element_text( size = 12, face = 'bold', color = 'black'),
            axis.text.x = element_blank(),
            # axis.text.x = element_text( size = 12, face = 'bold', color = 'black', angle = 90),
            axis.ticks.x = element_blank(),
            strip.background = element_rect(size=20, color = "grey80"),
            strip.text.x = element_text(size = 16, color = 'black'),
            legend.position = "bottom",
            
            panel.background = element_rect(fill = "white", colour = "grey50", size = .7),
            
            # panel.border = element_rect(color = "white"),
            
            panel.grid = element_blank()
        ) + 
        facet_wrap(facets = vars(variable), nrow = 1, scales = 'fixed')
    
    # pic
    if(nrow(obj@label_position_df) > 0){
        ### If there is any labels(significant changes between groups), then visualize it.
        # obj@label_position_df$variable
      obj@label_position_df %>%
        head() %>%
        print()
        pic <- pic +
            # geom_segment(data = obj@label_position_df,
            #              aes(x = start_num, xend = start_num + 0.25 * (end_num - start_num),
            #                  y = label.y, yend = label.y), lineend = 'butt', size = segment_size)+
            # geom_segment(data = obj@label_position_df, 
            #              aes(x = end_num, xend = start_num + 0.75 * (end_num - start_num),
            #                  y = label.y, yend = label.y), 
            #              lineend = 'butt', size = segment_size)+

            geom_text(data = obj@label_position_df, 
                      # angle = 90,
                      aes(x = 0.5 *(start_num + end_num), y = label.y*1.006, label = label)
                      # aes(x = 0.5 *(start_num + end_num), y = label.y*1.04, label = label)
                      ,color = 'black', size = 6
                      ,hjust = .5
                      ,vjust = .5
                      # vjust = 0
                      
            ) +
            geom_segment(data = obj@label_position_df,
                         aes(x = start_num, xend = start_num, 
                             y = label.y, yend = label.y * .995), 
                         lineend = 'round', size = segment_size)+
            geom_segment(data = obj@label_position_df, aes(x = end_num, xend = end_num, 
                                                           y = label.y, yend = label.y * .995), 
                         lineend = 'round', size = segment_size)+
            geom_segment(data = obj@label_position_df, aes(x = start_num, xend = end_num, 
                                                           y = label.y, yend = label.y),
                         size = segment_size) 
        
        
    }
    
    
    { ## output the results.
        # plot_name <- sprintf('%splot with sig labels #%s.pdf',output_path, each_note)
        plot_name <- sprintf('%splot with sig labels #%s.jpg',output_path, each_note)
        # csv_name <- plot_name %>% sub(".pdf$", ".csv", .)
        # obj@result_df %>% write.csv(., csv_name, row.names = F)
        # ggsave(plot_name, plot = pic, width = number_in_row * 2.7, height = 12, 
        ggsave(plot_name, plot = pic, device = "jpeg", 
               width = number_in_row * 1.7, height = 12, 
               limitsize = F, family = 'sans')
        # limitsize = F, family = 'mono')
        # limitsize = F, family = 'serif')
    }
    
}

pic
